`include "../include/cpu_defines.sv"
`define EXE_COP0    6'b010000
`define EXE_TLBP    6'b001000
`define EXE_TLBR    6'b000001
`define EXE_TLBWI   6'b000010
`define EXE_TLBWR   6'b000110
`define EXE_WAIT 	6'b100000

module DCU(
	input logic cpu_rst_n,
	input logic [31: 0] inst,
	input logic [31: 0] inst_addr,
	input logic [`EXC_CODE_BUS] id_id_exccode_in,
	output logic [5: 0] inst_rs,
	output logic [5: 0] inst_rt,
	output logic [5: 0] inst_rd,
	output logic [31: 0] inst_src1,
	output logic [31: 0] inst_src2,
	output logic [`INST_TYPE_BUS] inst_type,
	output logic [`ALUOP_BUS] aluop,
	output logic multdiv,
	output logic j_inst,
	output logic branch_inst,
	output logic [`EXC_CODE_BUS] id_exccode,
	output logic [`CP0OP_BUS]cp0op,
	output logic exception_type,
	output logic rasup,
	output logic rasdown,
	output logic [`MEMOP_BUS] memop,
	output logic [`MULTOP_BUS] multop,
	output logic place2, // 指令需要占据两条指令的空间
	output logic inst_madd,
	output logic mul,
	output logic [31: 0] imm5c
);
	logic [5: 0] op;
	logic [5: 0] func;
	logic [31: 0] inst_addr8;
	logic [4: 0] rs, rt;

	logic add, addi, addu, addiu, sub, subu, slt, slti, sltu, sync,
	sltiu, div, divu, mult, multu, _and, andi, lui, _nor, _or,
	ori, _xor, xori, sllv, sll, srav, sra, srlv, srl, beq, bne
	, _reg, j, jal, jr, mfhi, mflo, mthi, mtlo, lb, lbu, lh, lhu
	, lw, sb, sh, sw, lwl, lwr, swl, swr, ll, sc, bgez, bgtz, blez, bltz, bgezal, bltzal, ge, g, jalr,bgez_before;
	logic mfc0, mtc0, eret, syscall, _break, RI;
	logic hilo, trap;
	logic cache, pref, _wait;
	logic TLT, TLTI, TLTU, TLTIU, TGE, TGEI, TGEU, TGEIU, TEQ, TEQI, TNE, TNEI, TLBWI, TLBWR, TLBP, TLBR;
	logic tlb_type;
	logic cop0;
	logic match;
	logic movn, movz;
	logic madd, maddu, msub, msubu;
	logic write_hi;
	logic clo, clz;
	logic rlwinm;
	assign rlwinm = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & op[0] & inst[15];

	// 浮点指令，报CpU例外
	logic cop1, float_instr, cfc1, ctc1, ldc1, lwc1, mtc1, mfc1, sdc1, swc1;
	assign cop1 = ~op[5] & op[4] & ~op[3] & ~op[2] & ~op[1] & op[0];
	assign float_instr = cfc1 | ctc1 | ldc1 | lwc1 | mtc1 | mfc1 | sdc1 | swc1;
	assign cfc1 = cop1 & ~inst[25] & ~inst[24] & ~inst[23] & inst[22] & ~inst[21];
	assign ctc1 = cop1 & ~inst[25] & ~inst[24] & inst[23] & inst[22] & ~inst[21];
	assign ldc1 = op[5] & op[4] & ~op[3] & op[2] & ~op[1] & op[0];
	assign lwc1 = op[5] & op[4] & ~op[3] & ~op[2] & ~op[1] & op[0];
	assign mfc1 = cop1 & ~inst[25] & ~inst[24] & ~inst[23] & ~inst[22] & ~inst[21];
	assign mtc1 = cop1 & ~inst[25] & ~inst[24] & inst[23] & ~inst[22] & ~inst[21];
	assign sdc1 = op[5] & op[4] & op[3] & op[2] & ~op[1] & op[0];
	assign swc1 = op[5] & op[4] & op[3] & ~op[2] & ~op[1] & op[0];

	assign op = inst[31: 26];
	assign func = inst[5: 0];
	assign rs = inst[25: 21];
	assign rt = inst[20: 16];
	assign inst_addr8 = inst_addr + 8;

	assign _reg = ~|op;
	assign cop0 = ~op[5] & op[4] & ~op[3] & ~op[2] & ~op[1] & ~op[0];
    assign add = _reg & func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & ~func[0];
    assign addi =  ~op[5] & ~op[4] & op[3] & ~op[2] & ~op[1] & ~op[0] ;
    assign addu = _reg & func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & func[0];
    assign addiu =  ~op[5] & ~op[4] & op[3] & ~op[2] & ~op[1] & op[0] ;
    assign sub = _reg & func[5] & ~func[4] & ~func[3] & ~func[2] & func[1] & ~func[0];
    assign subu = _reg & func[5] & ~func[4] & ~func[3] & ~func[2] & func[1] & func[0];
    assign slt = _reg & func[5] & ~func[4] & func[3] & ~func[2] & func[1] & ~func[0];
    assign slti =  ~op[5] & ~op[4] & op[3] & ~op[2] & op[1] & ~op[0] ;
    assign sltu = _reg & func[5] & ~func[4] & func[3] & ~func[2] & func[1] & func[0];
    assign sltiu =  ~op[5] & ~op[4] & op[3] & ~op[2] & op[1] & op[0] ;
    assign div = _reg & ~func[5] & func[4] & func[3] & ~func[2] & func[1] & ~func[0];
    assign divu = _reg & ~func[5] & func[4] & func[3] & ~func[2] & func[1] & func[0];
	assign mul = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & ~func[5] & ~func[4] & ~func[3] & ~func[2] & func[1] & ~func[0];
	assign madd = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & ~func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & ~func[0];
	assign maddu = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & ~func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & func[0];
	assign msub = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & ~func[5] & ~func[4] & ~func[3] & func[2] & ~func[1] & ~func[0];
	assign msubu = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & ~func[5] & ~func[4] & ~func[3] & func[2] & ~func[1] & func[0];
    assign mult = _reg & ~func[5] & func[4] & func[3] & ~func[2] & ~func[1] & ~func[0];
    assign multu = _reg & ~func[5] & func[4] & func[3] & ~func[2] & ~func[1] & func[0];
    assign _and = _reg & func[5] & ~func[4] & ~func[3] & func[2] & ~func[1] & ~func[0];
    assign andi =  ~op[5] & ~op[4] & op[3] & op[2] & ~op[1] & ~op[0] ;
    assign lui =  ~op[5] & ~op[4] & op[3] & op[2] & op[1] & op[0] ;
    assign _nor = _reg & func[5] & ~func[4] & ~func[3] & func[2] & func[1] & func[0];
    assign _or = _reg & func[5] & ~func[4] & ~func[3] & func[2] & ~func[1] & func[0];
    assign ori =  ~op[5] & ~op[4] & op[3] & op[2] & ~op[1] & op[0] ;
    assign _xor = _reg & func[5] & ~func[4] & ~func[3] & func[2] & func[1] & ~func[0];
    assign xori =  ~op[5] & ~op[4] & op[3] & op[2] & op[1] & ~op[0] ;
    assign sllv = _reg & ~func[5] & ~func[4] & ~func[3] & func[2] & ~func[1] & ~func[0];
    assign sll = _reg & ~func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & ~func[0];
    assign srav = _reg & ~func[5] & ~func[4] & ~func[3] & func[2] & func[1] & func[0];
    assign sra = _reg & ~func[5] & ~func[4] & ~func[3] & ~func[2] & func[1] & func[0];
    assign srlv = _reg & ~func[5] & ~func[4] & ~func[3] & func[2] & func[1] & ~func[0];
    assign srl = _reg & ~func[5] & ~func[4] & ~func[3] & ~func[2] & func[1] & ~func[0];
	assign hilo =  _reg & ~func[5] & func[4] & ~func[3] & ~func[2];
    assign mfhi = hilo & ~func[1] & ~func[0];
    assign mflo = hilo & func[1] & ~func[0];
    assign mthi = hilo & ~func[1] & func[0];
    assign mtlo = hilo & func[1] & func[0];
    assign lb =  op[5] & ~op[4] & ~op[3] & ~op[2] & ~op[1] & ~op[0] ;
    assign lbu =  op[5] & ~op[4] & ~op[3] & op[2] & ~op[1] & ~op[0] ;
    assign lh =  op[5] & ~op[4] & ~op[3] & ~op[2] & ~op[1] & op[0] ;
    assign lhu =  op[5] & ~op[4] & ~op[3] & op[2] & ~op[1] & op[0] ;
    assign lw =  op[5] & ~op[4] & ~op[3] & ~op[2] & op[1] & op[0] ;
    assign sb =  op[5] & ~op[4] & op[3] & ~op[2] & ~op[1] & ~op[0] ;
    assign sh =  op[5] & ~op[4] & op[3] & ~op[2] & ~op[1] & op[0] ;
    assign sw =  op[5] & ~op[4] & op[3] & ~op[2] & op[1] & op[0] ;
	assign lwl = op[5] & ~op[4] & ~op[3] & ~op[2] & op[1] & ~op[0];
	assign lwr = op[5] & ~op[4] & ~op[3] & op[2] & op[1] & ~op[0];
	assign swl = op[5] & ~op[4] & op[3] & ~op[2] & op[1] & ~op[0];
	assign swr = op[5] & ~op[4] & op[3] & op[2] & op[1] & ~op[0];
	assign ll = op[5] & op[4] & ~op[3] & ~op[2] & ~op[1] & ~op[0];
	assign sc = op[5] & op[4] & op[3] & ~op[2] & ~op[1] & ~op[0];
	assign sync = _reg & ~func[5] & ~func[4] & func[3] & func[2] & func[1] & func[0];

	assign cache = op[5] & ~op[4] & op[3] & op[2] & op[1] & op[0];
	assign pref = op[5] & op[4] & ~op[3] & ~op[2] & op[1] & op[0];
	assign match = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & func[5] & func[4] & ~func[3] & func[2] & func[1] & func[0] & inst[10] & inst[9] & inst[8] & ~inst[7] & ~inst[6];
	assign movn = _reg & ~func[5] & ~func[4] & func[3] & ~func[2] & func[1] & func[0];
	assign movz = _reg & ~func[5] & ~func[4] & func[3] & ~func[2] & func[1] & ~func[0];
	assign clo = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & func[0];
	assign clz = ~op[5] & op[4] & op[3] & op[2] & ~op[1] & ~op[0] & func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & ~func[0];

    
	//异常
	assign mfc0 = cop0 & ~inst[25] & ~inst[24] & ~inst[23] & ~inst[22] & ~inst[21];
	assign mtc0 = cop0 & ~inst[25] & ~inst[24] & inst[23] & ~inst[22] & ~inst[21];
	assign eret = cop0 & inst[25] & ~func[5] & func[4] & func[3] & ~func[2] & ~func[1] & ~func[0];
	// assign trap = _reg & ~func[5] & ~func[4] & func[3] & func[2];
	assign syscall = _reg & ~func[5] & ~func[4] & func[3] & func[2] & ~func[1] & ~func[0];
    assign _break = _reg & ~func[5] & ~func[4] & func[3] & func[2] & ~func[1] & func[0];

	//trap 信号

	// TLT: op = < 
	//Trap if Less Than To compare GPRs and do a conditional trap
	//if GPR[rs] < GPR[rt] then Trap
	assign TLT = (op == 0 && func == 6'b110010) ;
	// Trap if Less Than Immediate To compare a GPR to a constant and do a conditional trap
	// if GPR[rs] < immediate then Trap
	assign TLTI = (op == 1 && rt == 5'b01010 );
	//Trap if Less Than Immediate Unsigned To compare a GPR to a constant and do a conditional trap
	//if GPR[rs] < immediate then Trap
	assign TLTIU = (op == 1 && rt == 5'b01011);
	//Trap if Less Than Unsigned To compare GPRs and do a conditional trap
	//if GPR[rs] < GPR[rt] then Trap
	assign TLTU = (op == 0 && func == 6'b110011) ;

	// TGE: op = (>=)
	//Purpose: Trap if Greater or Equal To compare GPRs and do a conditional trap
	//Description: if GPR[rs] ≥ GPR[rt] then Trap
	assign TGE = (op == 0 && func == 6'b110000);
	//Purpose: Trap if Greater or Equal Immediate To compare a GPR to a constant and do a conditional trap
	//Description: if GPR[rs] ≥ immediate then Trap
	assign TGEI = (op == 1 && rt == 5'b01000 ) ;
	//Purpose: Trap if Greater or Equal Immediate Unsigned To compare a GPR to a constant and do a conditional trap
	//Description: if GPR[rs] ≥ immediate then Trap
	assign TGEIU = (op == 1 && rt == 5'b01001 ) ;
	//Purpose: Trap if Greater or Equal Unsigned To compare GPRs and do a conditional trap
	//Description: if GPR[rs] ≥ GPR[rt] then Trap
	assign TGEU = (op == 0 && func == 6'b110001) ;

	// TEQ: op = (=?)
	//Trap if Equal To compare GPRs and do a conditional trap
	// if GPR[rs] = GPR[rt] then Trap
	assign TEQ = (op == 0 && func == 6'b110100) ;
	//Purpose: Trap if Equal Immediate To compare a GPR to a constant and do a conditional trap
	//Description: if GPR[rs] = immediate then Trap
	assign TEQI = (op == 6'b000001 && rt == 5'b01100) ;

	// TNE: op = (!=)
	//Purpose: Trap if Not Equal To compare GPRs and do a conditional trap
	//Description: if GPR[rs] ≠ GPR[rt] then Trap
	assign TNE = (op == 0 && func == 6'b110110) ;
	//Purpose: Trap if Not Equal Immediate To compare a GPR to a constant and do a conditional trap
	//Description: if GPR[rs] ≠ immediate then Trap
	assign TNEI = (op == 1 && rt == 5'b01110 ) ;

	assign TLBWI 	= cop0 & inst[25] & ~func[5] & ~func[4] & ~func[3] & ~func[2] & func[1] & ~func[0];
	assign TLBP 	= cop0 & inst[25] & ~func[5] & ~func[4] & func[3] & ~func[2] & ~func[1] & ~func[0];
	assign TLBR 	= cop0 & inst[25] & ~func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & func[0];
	assign TLBWR 	= cop0 & inst[25] & ~func[5] & ~func[4] & ~func[3] & func[2] & func[1] & ~func[0];
	assign _wait 	= cop0 & inst[25] & func[5] & ~func[4] & ~func[3] & ~func[2] & ~func[1] & ~func[0];
	assign tlb_type = TLBWI | TLBP | TLBR | TLBWR;

	assign RI = ~(match | ll | sc | lwl | lwr | swl | swr | mul | 
				 eret | mfc0 | mtc0 | blez | bltz | bgezal | bltzal | 
				 jalr | bgtz | bgez |
				 _break | syscall | 
				 TLT | TLTI | TLTU | TLTIU |
				 TGE | TGEI | TGEU | TGEIU |
				 TEQ | TEQI | TNE | TNEI | 
				 TLBWI | TLBP | TLBR | TLBWR |
				 sw | sh | sb | lw | lhu | lh | lbu | lb | 
				 mtlo | mthi | mflo | mfhi | 
				 jr | jal | j |bne |beq |  
				 srl| srlv| sra | srav | sll | sllv |  
				 xori | _xor | ori | _or | _nor| lui | andi | _and| 
				 multu | mult | divu | div |
				 sltiu | sltu | slti | slt | 
				 subu | sub | addiu | addu | addi | add |
				cache | pref | sync | _wait
				 | movn | movz | madd | maddu | msub | msubu | clo | clz | float_instr | rlwinm);


	assign j =  ~op[5] & ~op[4] & ~op[3] & ~op[2] & op[1] & ~op[0] ;
    assign jal =  ~op[5] & ~op[4] & ~op[3] & ~op[2] & op[1] & op[0] ;
    assign jr = _reg & ~func[5] & ~func[4] & func[3] & ~func[2] & ~func[1] & ~func[0];
	assign beq =  ~op[5] & ~op[3] & op[2] & ~op[1] & ~op[0] ; // beq || beql
    assign bne =  ~op[5] & ~op[3] & op[2] & ~op[1] & op[0] ; // bne || bnel
	assign bgez_before = ~op[5] & ~op[4] & ~op[3] & ~op[2] & ~op[1] & op[0];
	assign bgez =  bgez_before & ~inst[20] & inst[16];
	assign bgtz = ~op[5] & ~op[3] & op[2] & op[1] & op[0]; // bgtz || bgtzl
	assign blez = ~op[5] & ~op[3] & op[2] & op[1] & ~op[0] & ~inst[20] & ~inst[19] & ~inst[18] & ~inst[17] & ~inst[16]; // blez || blezl
	assign bltz = bgez_before & ~inst[20] & ~inst[16];
	assign bgezal = bgez_before & inst[20] & inst[16];
	assign bltzal = bgez_before & inst[20] & ~inst[16];
	assign jalr = _reg & ~func[5] & ~func[4] & func[3] & ~func[2] & ~func[1] & func[0];

	assign j_inst = beq | bne | bgez_before | bgtz | blez;
	assign rasup = bgezal | bltzal | jal | jalr;
	assign rasdown = (jr | jalr) & (inst[25: 21] == 32'd31);

	logic j_type, mem_type;
	assign j_type = beq | bne | bgez_before | bgtz | blez | jr | jalr;
	assign branch_inst = beq | bne | bgez_before | bgtz | blez | jr | jalr | j | jal;
	assign mem_type = lb | lbu | lh | lhu | lw | sb | sh | sw | swl | swr | lwr | lwl | ll | sc;
	assign multdiv = mult | multu | div | divu | mul | madd | maddu | msub | msubu;
	assign place2 = mult | multu | div | divu | mul | madd | maddu | msub | msubu;
	assign inst_madd = madd | maddu | msub | msubu;
	assign write_hi = mult | multu | div | divu | madd | maddu | msub | msubu;

	always_comb begin
		if(j_type)begin
			inst_type = `INST_TYPE_BRANCH;
		end
		else if(multdiv)begin
			inst_type = `INST_TYPE_MULT;
		end
		else if(mem_type)begin
			inst_type = `INST_TYPE_MEM;
		end
		else if(exception_type )begin
			inst_type = `INST_TYPE_CP0;
		end
		else begin
			inst_type = `INST_TYPE_ALU;
		end
	end

	logic immsel, sext, t_inst;
	logic [31: 0] imm, signed_imm, out_imm, ans_imm, branch_addr;
	assign immsel = addi | addiu | slti | sltiu | 
					andi | lui | ori | xori | 
					lb | lbu | lh | lhu | lw | 
					sb | sh | sw | lwl | lwr | swl | swr | 
					ll | sc | 
					TLTI | TLTIU | TGEI | TGEIU | TNEI | TEQI |
					cache | rlwinm;

	assign sext = 	addi | addiu | slti | sltiu | 
					lb | lbu | lh | lhu | lw | 
					sb | sh | sw | lwl | lwr | swl | swr | ll | sc | 
					TLTI | TLTIU |TGEI | TGEIU | TNEI | TEQI |
					cache;
	assign imm = inst[15: 0];
	assign signed_imm = inst[15] ? {16'hffff, imm[15: 0]} : imm;
	assign out_imm = sext ? signed_imm : imm;
	assign ans_imm = lui ? (imm << 16) : (beq | bne | bgez_before | bgtz | blez) ? branch_addr : out_imm;
	assign branch_addr = (signed_imm << 2) + inst_addr + 4;
	assign exception_type = mtc0 | mfc0 | TLBWI | TLBWR | TLBP | TLBR | _wait | cache;

	assign t_inst = TLT | TLTI | TLTIU | TLTU |
					TGE | TGEI | TGEIU | TGEU |
					TNE | TNEI | TEQ   | TEQI ;
	logic rtsel, shift, nwreg;
	logic rs_unuseful, rt_unuseful;
	assign shift = sll | sra | srl;
	assign rtsel = addi | addiu | slti | sltiu | andi | lui | ori | xori | lb | lbu | lh | lhu | lw | mfc0 | lwl | lwr | ll | sc | rlwinm;
	assign nwreg =  beq | bne | j | bgez | bltz | bgtz | blez  | 
					sb | sh | sw | swl | swr | 
					syscall | _break |
					t_inst | TLBP | TLBWI | TLBWR | TLBR | 
					mtc0 | cache | pref | _wait;
	assign rs_unuseful = j | jal | pref;
	assign rt_unuseful = addi | addiu | slti | sltiu | 
						 andi | lui | ori | xori | 
						 lb | lbu | lh | lhu | lw | ll | 
						 mfc0 | cache | pref |
						 bgez_before | bgtz | blez | 
						 j | jal | 
						 TNEI | TEQI | TGEI | TLTI | TLTIU | TGEIU | rlwinm;

	assign inst_rs = 	rs_unuseful 		? 0 : 
						mtc0 | mfc0 		? {inst[0], inst[15: 11]} :
						mfhi 				? `REG_HI :
						mflo 				? `REG_LO : 
						inst[25: 21];

	assign inst_rt = 	rt_unuseful 		? 5'b0 : 
						inst[20: 16];
	
	assign inst_src1 = shift ? inst[10: 6] : cache ? inst[20: 16] :  32'b0;
	assign inst_src2 = 	bgezal | bltzal | jal | jalr ? inst_addr8 : 
						immsel ? ans_imm : 0;
	assign inst_rd = nwreg ? 6'b0 : rtsel ? inst[20: 16] : jal || bgezal || bltzal ? 6'b11111 : mthi ? `REG_HI : mtlo ? `REG_LO : write_hi ? `REG_HI : inst[15: 11];


	assign aluop[7] = beq | bne | bgez_before | bgtz | blez | jalr | t_inst | match | movn | movz | clo | clz;
	assign aluop[6] = _nor | _or | xori | sllv | sra | srav | srl | srlv | t_inst | match;
	assign aluop[5] = slt | slti | sltu | sltiu | bne | beq | bne | bgez_before | bgtz | blez | jalr | jal | jr | match | rlwinm;
	assign aluop[4] = add | addi | addu | addiu | sub | subu | _and | andi | ori | _xor | sll | match | rlwinm;
	assign aluop[3] = add | addiu | subu | _and | ori | _xor | sra | srlv | mfhi | mflo | bgtz | blez | bltz | bltzal | jal | jr | match | clz;
	assign aluop[2] = _and | andi | lui | ori | sllv | srl | srlv | sltiu | mfhi | mflo | bgez | bgtz | bgezal | jalr | TNE | TEQ | clo;
	assign aluop[1] = addu | sub | subu | slt | andi | _xor | xori | srav | srl | bne | blez | bgezal | TGE | TGEU | movz | mthi | rlwinm;
	assign aluop[0] = addiu | sub | subu | sltu | lui | _or | ori | sll | srav | mflo | mtlo | beq | bltzal | jalr | jal | TLTIU | TGEU | TNE | match | rlwinm;

	assign memop[4] = sb | sh | sw | swl | swr | sc;
	assign memop[3] = lwl | lwr | swl | swr;
	assign memop[2] = lbu | lhu | lwr | swr | ll | sc;
	assign memop[1] = lw | sw | lwl | lwr | swl | swr | ll | sc;
	assign memop[0] = lh | lhu | sh;

	assign multop[3] = msubu;
	assign multop[2] = div | divu | madd | maddu;
	assign multop[1] = mul | div | divu | msub;
	assign multop[0] = multu | mul | divu | maddu;
	always_comb begin
		if(id_id_exccode_in != `EXC_NONE)begin
			id_exccode = id_id_exccode_in;
		end
		else if(syscall) begin
			id_exccode = `EXC_SYS;
		end
		else if(_break) begin
			id_exccode = `EXC_BREAK;
		end
		else if(eret)begin
			id_exccode = `EXC_ERET;
		end
		else if(tlb_type)begin
			id_exccode = `EXC_FLUSH;
		end
		else if(RI) begin
			id_exccode = `EXC_RI;
		end
		else if(float_instr)begin
			id_exccode = `EXC_CpU;
		end
		else begin
			id_exccode = `EXC_NONE;
		end
	end

	// assign cp0op  	= 	mtc0 ? `CP0OP_MTC0 :
	// 					mfc0 ? `CP0OP_MFC0 :
	// 					TLBWI ? `CP0OP_TLBWI :
	// 					TLBP ? `CP0OP_TLBP :
	// 					TLBR ? `CP0OP_TLBR :
	// 					TLBWR ? `CP0OP_TLBWR : 0 ;
	assign cp0op[2] = TLBR | TLBWI | TLBWR | _wait;
	assign cp0op[1] = mfc0 | TLBP | TLBWR | _wait;
	assign cp0op[0] = mtc0 | TLBP | TLBWI | _wait;


endmodule